package pl.edu.pw.elka.tinyrepo.common;

import java.util.EnumMap;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

/**
 * Klasa reprezentujaca zapytanie.</br>
 * Klasa odpowiada zapytaniu HTTP/1.1. Jest to wrapper dla przychodzacych z sieci
 * requestow. Po wywolaniu read klasa ta przechowuje pelne informacje o
 * requescie: jakiej metodzie odpowiada, sciezka do ktorej jest request oraz
 * odpowiednie headery ("Content-type: ..." itp.). </br>
 * <b> Klasa ta nie przechowuje danych do wyslania - za to po wywolaniu read
 * strumien jest ustawiony na poczatek danych</b>. Jest tak dlatego
 * ze czasami serwer nie chce czytac calej zawartosci danych, wystarczy mu
 * tylko np. sama metoda, sciezka i requesty - tak jest w przypadku
 * bramy, ktora nie powinna szczytywac danych dla metody PUT. Odczytywaniem danych
 * (np. plikow) powinien zajmowac sie odpowiedni handler.
 * 
 * @author Piotr Jarosik
 */
public class Request extends Message {
//   /** Request line (pierwsza linia) zapytania. */ // 
   /** Sciezka do pliku lub katalogu odczytania z request line. */
   private String path = null;  // FIXME zmienic nazwe na URI 
   /** Jaka metoda. */
   private WebDAVMethod method;
   /** Naglowki i odpowiadajace im wartosci w danym requescie.*/
   public Map<HTTPHeaderType, String> headers = 
                        new EnumMap<HTTPHeaderType, String>(HTTPHeaderType.class); // FIXME private
   
   /**
    * Tworzy pusty request.
    */
   public Request() {
      
   }
   
   /**
    * Tworzy Request i wczytuje parametry requesta na podstawie requestLine.
    * 
    * @see Request#setRequestLine(String)
    * @param requestLine
    */
   public Request(String requestLine) {
      setRequestLine(requestLine);
   }
   
   /**
    * Tworzy request na podstawie nazwy hosta.
    * 
    * @param method
    * @param path
    */
   public Request(WebDAVMethod method, String path) {
      this.method = method;
      this.path = path;
   }
   
   /**
    * Ustawia nowe parametry requesta na podstawie request line.
    * 
    * Uwaga: W przypadku nieprawidlowego protokolu pole method jest ustawiane jako null.
    * 
    * @param requestLine
    */
   public void setRequestLine(String requestLine) {
      StringTokenizer t = new StringTokenizer(requestLine);
      method = WebDAVMethod.valueOf(t.nextToken()); // FIXME nie powinno byc wyjatku, ale... jak cos tu walnie tzn. ze brakuje odpowiedniego enuma w WebDAVMethod
      path = t.nextToken(); // wyciagniecie sciezki do pliku z zapytania.
      if(!t.nextToken().equals("HTTP/1.1")) // wersja protokolu
         setMethod(null); // FIXME przekazywanie informacji ze nie poprawny protokol przez ustawienie nulla jako metody. 
   }

   /**
    * @return request line.
    */
   public String getFirstLine() {
      return method+" "+path+" HTTP/1.1";
   }
   
   /**
    * @return sciezka do wymaganego pliku.
    */
   public String getPath() {
      return path;
   }
   
   /**
    * @return metoda requesta (GET, PUT, etc.).
    */
   public WebDAVMethod getMethod() {
      return method;
   }
   
   /**
    * Setter metody dla Requesta.
    * 
    * @param method
    */
   public void setMethod(WebDAVMethod method) {
      this.method = method;
   }
   
   /**
    * Setter sciezki dla Requesta.
    * 
    * @param path
    */
   public void setPath(String path) {
      if(path == null) 
         return;
      else this.path = path;
   }
 
   @Override
   public void addHeader(HTTPHeaderType t, String value) {
      if(!t.isProperValue(value)) { // zlych wartosci nie wstawiamy
         System.err.println("Wrong "+t+" value.");
         return;
      }
      headers.put(t, value);
   }
   
   @Override
   public String getHeader(HTTPHeaderType t) {
      return headers.get(t);
   }

   @Override
   Set<HTTPHeaderType> getHTTPTypes() {
      return headers.keySet();
   }
   

}
